import os
import uuid
import requests
from fastapi import UploadFile, File, Form, HTTPException, Request, Response
from fastapi.responses import JSONResponse, FileResponse
import pillow_avif
from PIL import Image
from io import BytesIO
from typing import Optional, Dict, Any
from app.setting import settings
# 导入pillow-avif-plugin和pillow-heif (无需显式导入，但需要安装这些插件)

class ImageTransformerAPI:
    def __init__(self):
        self.static_path = f"{settings.STATIC_PATH}/images"
        self.static_dir = f"{settings.STATIC_DIR}/images"
        os.makedirs(self.static_dir, exist_ok=True)
        
        # 格式映射表，将输入格式映射到PIL支持的格式
        self.format_mapping = {
            'jpg': 'JPEG',
            'jpeg': 'JPEG',
            'png': 'PNG',
            'webp': 'WEBP',
            'gif': 'GIF',
            'bmp': 'BMP',
            'tiff': 'TIFF',
            'tif': 'TIFF',
            'ico': 'ICO',
            'avif': 'AVIF'
        }
        
        # 支持的输入和输出格式
        self.supported_formats = list(self.format_mapping.keys())
        
    async def handle(self, request: Request, format: str, type: str = "json", url: Optional[str] = None, 
                    file: Optional[UploadFile] = None, quality: Optional[int] = None):
        """
        处理图片格式转换请求
        
        Args:
            request: 请求对象
            format: 目标图片格式 (如 'png', 'jpg', 'webp', 'avif' 等)
            type: 返回类型，'json' 返回图片URL，'image' 返回图片文件
            url: GET请求时的远程图片URL
            file: POST请求时上传的图片文件
            quality: 图片质量 (1-100)，仅对支持质量设置的格式有效
        
        Returns:
            根据type参数返回JSONResponse或FileResponse
        """
        # 验证格式参数
        format = format.lower()
        if format not in self.supported_formats:
            raise HTTPException(status_code=400, 
                               detail=f"不支持的格式: {format}，支持的格式有: {', '.join(self.supported_formats)}")
        
        # 获取PIL格式
        pil_format = self.format_mapping.get(format)
        
        # 获取图片数据
        if request.method == "GET":
            if not url:
                raise HTTPException(status_code=400, detail="GET请求必须提供url参数")
            try:
                response = requests.get(url, timeout=10)
                response.raise_for_status()
                image_data = BytesIO(response.content)
            except Exception as e:
                raise HTTPException(status_code=400, detail=f"获取远程图片失败: {str(e)}")
        else:  # POST
            if not file:
                raise HTTPException(status_code=400, detail="POST请求必须上传文件")
            image_data = BytesIO(await file.read())
        
        # 转换图片格式
        try:
            img = Image.open(image_data)
            
            # 生成唯一文件名
            filename = f"{uuid.uuid4()}.{format}"
            file_path = os.path.join(self.static_dir, filename)
            
            # 处理图片模式转换
            img = self._handle_image_mode(img, format)
            
            # 准备保存参数
            save_kwargs = self._prepare_save_kwargs(format, quality)
            
            # 保存转换后的图片
            img.save(file_path, format=pil_format, **save_kwargs)
            
            # 生成URL
            image_url = f"{self.static_path}/{filename}"
            
            # 根据type参数返回不同的响应
            if type.lower() == "json":
                return JSONResponse(content={"success": True, "url": image_url})
            else:  # type == "image"
                return FileResponse(
                    path=file_path, 
                    filename=filename,
                    media_type=f"image/{format}"
                )
                
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"图片处理失败: {str(e)}")
    
    def _handle_image_mode(self, img: Image.Image, format: str) -> Image.Image:
        """处理图片模式转换"""
        # 如果原图是RGBA模式但目标格式不支持透明度，转换为RGB
        if img.mode == 'RGBA' and format in ['jpg', 'jpeg']:
            return img.convert('RGB')
        
        # 如果是CMYK模式，转换为RGB
        if img.mode == 'CMYK':
            return img.convert('RGB')
        
        # 如果是P模式(调色板)，对于某些格式可能需要转换
        if img.mode == 'P' and format not in ['png', 'gif']:
            return img.convert('RGB')
            
        return img
    
    def _prepare_save_kwargs(self, format: str, quality: Optional[int] = None) -> Dict[str, Any]:
        """准备图片保存参数"""
        kwargs = {}
        
        # 处理质量参数
        if quality is not None:
            # 确保质量在有效范围内
            quality = max(1, min(100, quality))
            
            # 对于支持质量设置的格式，添加质量参数
            if format in ['jpg', 'jpeg', 'webp', 'avif']:
                kwargs['quality'] = quality
        
        # 特定格式的额外参数
        if format == 'webp':
            # WebP可以设置无损压缩
            if quality == 100:
                kwargs['lossless'] = True
        
        elif format == 'png':
            # PNG可以设置压缩级别
            if quality is not None:
                # 将1-100的质量转换为0-9的压缩级别(9为最高压缩)
                compression = 9 - int(quality / 100 * 9)
                kwargs['compress_level'] = compression
                
        elif format in ['tiff', 'tif']:
            # TIFF可以设置压缩方式
            kwargs['compression'] = 'tiff_deflate'
            
        return kwargs
